package com.zh.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zh.common.ErrorCode;
import com.zh.domain.dto.message.MessageQueryRequest;
import com.zh.domain.dto.message.MessageReadRequest;
import com.zh.domain.entity.Message;
import com.zh.domain.entity.MessageReceiver;
import com.zh.domain.entity.User;
import com.zh.domain.vo.message.MessageVo;
import com.zh.domain.vo.user.UserVO;
import com.zh.exception.ThrowUtils;
import com.zh.mapper.MessageReceiverMapper;
import com.zh.service.MessageReceiverService;
import com.zh.service.MessageService;
import com.zh.mapper.MessageMapper;
import com.zh.service.UserService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Administrator
 * @description 针对表【messages(消息表)】的数据库操作Service实现
 * @createDate 2025-02-09 16:24:10
 */
@Service
public class MessageServiceImpl extends ServiceImpl<MessageMapper, Message> implements MessageService {

    @Resource
    private MessageMapper messageMapper;
    @Resource
    private MessageReceiverMapper messageReceiverMapper;
    @Resource
    private MessageReceiverService messageReceiverService;
    @Resource
    private UserService userService;

    @Override
    @Transactional
    public String sendMessage(Message message, List<Integer> receiveIds) {
        //1.参数校验
        Integer sendId = message.getSendId();
        String content = message.getContent();
        ThrowUtils.throwIf(sendId == null || receiveIds.isEmpty() || StrUtil.isEmpty(content), ErrorCode.PARAMS_ERROR);
        //2.保存到消息表
        messageMapper.insert(message);
        //3.保存到消息接收表
        List<MessageReceiver> messageReceivers = new ArrayList<>();
        for (Integer receiveId : receiveIds) {
            MessageReceiver messageReceiver = new MessageReceiver();
            messageReceiver.setMessageId(message.getId());
            messageReceiver.setReceiverId(receiveId);
            messageReceiver.setStatus(1);
            messageReceivers.add(messageReceiver);
        }
        messageReceiverService.saveBatch(messageReceivers);
        return "发送成功";
    }

    @Override
    public Page<MessageVo> pageMessages(MessageQueryRequest queryRequest) {
        //1.参数校验
        int loginId = StpUtil.getLoginIdAsInt();
        Integer receiverId = queryRequest.getReceiverId();
        if (receiverId == null) {
            queryRequest.setReceiverId(loginId);
        }
        queryRequest.standardizeSize();
        Integer status = queryRequest.getStatus();
        if (status != null && status == 1) {
            queryRequest.setSortField("create_at");
        }
        //2.查找符合条件的消息
        Page<MessageVo> page = new Page<>(queryRequest.getCurrent(), queryRequest.getPageSize());
        List<MessageVo> list = messageMapper.page(page, queryRequest);
        //3.提取发送者和接收者id
        Set<Integer> userIdSet = new HashSet<>();
        list.forEach(messageVo -> {
            userIdSet.add(messageVo.getSendId());
            userIdSet.add(messageVo.getReceiverId());
        });
        List<Integer> userIdList = new ArrayList<>(userIdSet);
        //3.查询发送者和接收者信息
        Map<Integer, UserVO> userVOMap;
        if (CollectionUtil.isNotEmpty(userIdList)) {
            List<User> users = userService.listByIds(userIdList);
            userVOMap = users.stream().map(User::toUserVo).collect(Collectors.toMap(UserVO::getId, userVO -> userVO));
            //4.封装结果
            Map<Integer, UserVO> finalUserVOMap = userVOMap;
            list.forEach(messageVo -> {
                Integer receiverId1 = messageVo.getReceiverId();
                Integer sendId = messageVo.getSendId();
                messageVo.setSender(finalUserVOMap.get(sendId));
                messageVo.setReceiver(finalUserVOMap.get(receiverId1));
            });
        }
        page.setRecords(list);
        return page;
    }

    @Override
    public boolean read(MessageReadRequest messageReadRequest) {
        int loginId = StpUtil.getLoginIdAsInt();
        //1.参数校验
        List<Integer> messageIdList = messageReadRequest.getMessageIdList();
        Boolean all = messageReadRequest.getAll();
        ThrowUtils.throwIf(!all && CollectionUtil.isEmpty(messageIdList), ErrorCode.PARAMS_ERROR);
        //2.是否存在未读数据
        LambdaQueryWrapper<MessageReceiver> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MessageReceiver::getReceiverId, loginId)
                .eq(MessageReceiver::getStatus, 1)
                .eq(MessageReceiver::getDeleted, 0);
        boolean noData = messageReceiverService.count(queryWrapper) > 0;
        if (!noData) {
            return false;
        }
        //2.更新消息状态
        MessageReceiver messageReceiver = new MessageReceiver();
        LambdaUpdateWrapper<MessageReceiver> updateWrapper = new LambdaUpdateWrapper<>();
        if (all) {
            updateWrapper.eq(MessageReceiver::getReceiverId, loginId)
                    .eq(MessageReceiver::getStatus, 1)
                    .eq(MessageReceiver::getDeleted, 0)
                    .set(MessageReceiver::getStatus, 0)
                    .set(MessageReceiver::getUpdateAt, LocalDateTime.now())
                    .set(MessageReceiver::getUpdateBy, loginId);
        } else {
            updateWrapper.eq(MessageReceiver::getReceiverId, loginId)
                    .eq(MessageReceiver::getStatus, 1)
                    .eq(MessageReceiver::getDeleted, 0)
                    .in(MessageReceiver::getMessageId, messageIdList)
                    .set(MessageReceiver::getStatus, 0)
                    .set(MessageReceiver::getUpdateAt, LocalDateTime.now())
                    .set(MessageReceiver::getUpdateBy, loginId);
        }
        return messageReceiverMapper.update(messageReceiver, updateWrapper) > 0;
    }
}




